// Copyright (C) 2023 即时通讯网(52im.net) & Jack Jiang.
// The RainbowChat Project. All rights reserved.
// 
// 【本产品为著作权产品，合法授权后请放心使用，禁止外传！】
// 【本次授权给：<北京小羊驼科技有限公司>，授权编号：<NT231212144350>，代码指纹：<A.702363430.550>，技术对接人微信：<ID: wxid_wbyootvkdcgj22>】
// 【授权寄送：<收件：苏先生、地址：北京市大兴区北京密码西区6号楼1单元301、电话：18613885610、邮箱：bd@huiyuanxiang-inc.com>】
// 
// 【本系列产品在国家版权局的著作权登记信息如下】：
// 1）国家版权局登记名(简称)和权证号：RainbowChat    （证书号：软著登字第1220494号、登记号：2016SR041877）
// 2）国家版权局登记名(简称)和权证号：RainbowChat-Web（证书号：软著登字第3743440号、登记号：2019SR0322683）
// 3）国家版权局登记名(简称)和权证号：RainbowAV      （证书号：软著登字第2262004号、登记号：2017SR676720）
// 4）国家版权局登记名(简称)和权证号：MobileIMSDK-Web（证书号：软著登字第2262073号、登记号：2017SR676789）
// 5）国家版权局登记名(简称)和权证号：MobileIMSDK    （证书号：软著登字第1220581号、登记号：2016SR041964）
// * 著作权所有人：江顺/苏州网际时代信息科技有限公司
// 
// 【违法或违规使用投诉和举报方式】：
// 联系邮件：jack.jiang@52im.net
// 联系微信：hellojackjiang
// 联系QQ号：413980957
// 授权说明：http://www.52im.net/thread-1115-1-1.html
// 官方社区：http://www.52im.net
package com.x52im.rbchat.logic.chat_friend.vv;

import android.content.Context;
import android.hardware.Camera;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.eva.android.AppManager;
import com.eva.android.NewAsyncTask;
import com.eva.android.ToolKits;
import com.eva.android.widget.TimerViewWrapper;
import com.eva.android.widget.WidgetUtils;
import com.eva.android.widget.WidgetUtils.ToastType;
import com.eva.android.widget.alert.AlertDialog;
import com.eva.android.x.XToolKits;
import com.vc.core.VcConstants;
import com.x52im.rbchat.MyApplication;
import com.x52im.rbchat.R;
import com.x52im.rainbowchat.http.logic.dto.RosterElementEntity;
import com.x52im.rbchat.logic.chat_friend.utils.MessageHelper;
import com.x52im.rbchat.logic.chat_root.model.VoipRecordMeta;
import com.x52im.rbchat.utils.PromtHelper;
import com.x52im.rbchat.network.im.ChatMessageEventListener;

import net.x52im.rainbowav.sdk.AccountManager;
import net.x52im.rainbowav.sdk.activity.VideoActivity;
import net.x52im.rainbowav.sdk.iface.IReceiveEventListener;
import net.x52im.rainbowav.sdk.util.NetworkUtil;

/**
 * 不依赖第3方的自主产权视频聊天界面实现。
 * 
 * @author Jack Jiang(http://www.52im.net/space-uid-1.html)
 * @version 1.0
 */
public class VideoActivityNew extends VideoActivity implements IReceiveEventListener, IVideoActivity
{
	private final static String TAG = VideoActivityNew.class.getSimpleName();
	
	/** 是应答还是发起请求 */
	private boolean mReceive;
	/** 1语音、2视频 */
	private int chatType = 0; 
	/** 当前音视频者的uid */
	private long toAccount;
	/** 当前音视频者的基本信息 */
	private RosterElementEntity toFriend = null;
	/** 当前是前置还是后置设像头 */
    private boolean isBack = false;
    
    /** 前后摄像头切换按钮 */
    private ImageView mCameraSwitchImage;
	/** 屏幕常亮管理 */
	private PowerManager powerManager = null;
	private WakeLock wakeLock = null;

	/** 视频+音频和仅音频功能的切换开关组件 */
	private CheckBox video_room_videoOrOnlyVoiceSwitchBtn = null;
	/** 退出聊天按钮组件 */
	private View video_room_exitChattingBtn = null;
	/** 信息提示文本组件 */
	private TextView video_room_hintView = null;
	/** 根布局 */
	private ViewGroup mainLl = null;
	/** 仅音频模式下的提示父布局 */
	private ViewGroup video_room_voiceOnlyHintRL = null;
	/** 音频+视频模式下的视频显示组件父布局 */
	private ViewGroup video_room_voiceAndVideoRL = null;
	/**
	 * 说明：本变量值仅用于在收到对方的音视频聊天模式切换时有意义，其它时间无意义哦！
	 * 
	 * <p>
	 * true表示设置{@link #video_room_videoOrOnlyVoiceSwitchBtn}的是否checked状态时不触发它的
	 * OnClickListener，否则要触发，默认是false.
	 * 
	 * <p>
	 * 目前本变量为true时是在收到对方切换音视频聊天模式时在{@link ChatMessageEventListener}中被设置的，
	 * 用于设置{@link #video_room_videoOrOnlyVoiceSwitchBtn}的是否checked状态，之所以此时忽略
	 * {@link #video_room_videoOrOnlyVoiceSwitchBtn}的事件处理，是因为它的事件处理就是切换模式，
	 * 而在此情景下，{@link ChatMessageEventListener}中已经后台设置了本地用户的模式切换，而不需要也不应
	 * 该再次触发{@link #video_room_videoOrOnlyVoiceSwitchBtn}的事件处理.态
	 */
	private boolean ignorevideoOrOnlyVoiceSwitchBtnEvent = false;
	
	/** 当前是否真在（视频/语音）聊天中 */
	private static boolean chatting = false;
	
	/** UI组件：计时显示 */
	private TextView viewTimer = null;
	/** 包装实现类：计时器 */
	private TimerViewWrapper timerViewWrapper = null;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		// 全面屏沉浸式效果（系统顶部状态栏将变的透明，界面从状态栏下方透过）
		XToolKits.setStatusBarTranslucent(this, true);
		// 全面屏沉浸式效果（系统底部导航栏将变的透明，界面从导航栏下方透过）
		XToolKits.setNavigationBarTranslucent(this, true);

		super.onCreate(savedInstanceState);
		
		// 添加Activity到堆栈
		AppManager.getAppManager().addActivity(this);

		chatting = true;

		if(android.os.Build.VERSION.SDK_INT >= 11){
			getWindow().setFlags(0x01000000, 0x01000000);//开启硬件加速
		}

		initDataFromIntent();
		initViews();
		
		//----------------------------------------------------------------------------------------------------
		//* 初始化远程播放窗口
		initGLSurfaceView(R.id.surface_remote);	
		//* 初始化视频录制窗口
		initLocalSurfaceView(R.id.surface_local);
		//##### Bug FIX: 20170730 by JackJiang START =================================
		//##     在Android 4.4及以上版本，以下设置会导致本地预览的SurfaceView不显示内容，这是SurfaceView的
		//##     特性决定的，无法改变，但挡住其它UI显示的问题可以通过单独设置SurfaceView组件的可见性即可.
//		// ** 注意：在父类中的initLocalSurfaceView()会把localSurfaceView置顶显示，这样在它父布局里的其它组件就会被挡住，以下代码就是为了取消置顶
//		localSurfaceView.setZOrderOnTop(false);
		//##### Bug FIX: 20170730 by JackJiang END ===================================

		// 因为VcCamera是在父类的initVideoChat被初始化，所以以下代码放在此处执行
		// ** 当摄像头数多于1个时显示摄像头切换按钮
		if(Camera.getNumberOfCameras() > 1) {
			mCameraSwitchImage.setVisibility(View.VISIBLE);
		}

		if(myController==null){
			Log.e(TAG, "【VV】myController is null");
			finish();
		}
		//* 获取摄像头实例
		myCamera = myController.getVcCamera();
		//* 摄像头初始化失败，直接结束
		if (myCamera == null) {
			Log.e(TAG, "【VV】Create video failed because camera open failed.");
			this.finish();
			return;
		}

		int result = -1;

		if(mReceive) {
			//* 接受请求
			result = p2pController.receiveAction(AccountManager.myAccount,toAccount,NetworkUtil.getApn(this),chatType,0);
			if(!audioStart()) {
				Toast.makeText(this, "audioStart fail!", Toast.LENGTH_LONG).show();
				finish();
			}
		}
		else {
			//* 发起请求
			result = p2pController.requestAction(AccountManager.myAccount,toAccount,NetworkUtil.getApn(this),chatType);
			// 关闭麦克风，不发数据出去
			myController.mMicphone = true;
			// 先不开启声音，待对方接收后再放开
			myController.mSound = true;
		}

		//* 请求/应答失败
		if (result != 0) {
			Toast.makeText(this, "request or receive fail,errorCode="+result, Toast.LENGTH_LONG).show();
			Log.e(TAG, "action fail, chatType="+chatType);
			finish();
			return;
		}

		//* 注册事件接收器
		p2pController.registryRequestEventListener(this);
		//* 注册屏幕方向监听器
		registerOrientationListener();

		Log.d(TAG, "VideoChatActivity.onCreate...");
	}
	
	/**
	 * 从Intent中读取数据。
	 */
	protected void initDataFromIntent() {
		//* 是接收请求还是发起请求
		mReceive = super.getIntent().getBooleanExtra("receive", true);
		toAccount = super.getIntent().getLongExtra("toAccount",0);
		chatType = super.getIntent().getIntExtra("type",0);

		Log.d(TAG, "【VV】@@@ myAccount="+AccountManager.myAccount+",toAccount="+toAccount+",mReceive="+mReceive+",chatType="+chatType);
		
		//* 判断通话类型：无效的通话方式
		if(chatType != VcConstants.VIDEO && chatType != VcConstants.AUDIO) {
			WidgetUtils.showToastLong(this, "无效的通话方式！", ToastType.ERROR);
			Log.e(TAG, "无效的通话方式，chatType="+chatType);
			finish();
		}

		// 读取对方的好友信息
		toFriend = MyApplication.getInstance2().getIMClientManager().getFriendsListProvider().getFriendInfoByUid2(""+toAccount);
		if(toFriend == null){
			WidgetUtils.showToastLong(this, "无效的好友信息！", ToastType.ERROR);
			Log.e(TAG, "无效的好友信息，toFriend="+toFriend);
			finish();
		}
	}

	/**
	 * 初始化ui.
	 */
	private void initViews() {
		this.setContentView(R.layout.video_chatting_activity);

//		// 对界面上方进行全面屏设置
//		StatusBarUtils.immersiveStatusBar(this, findViewById(R.id.toolbar),0.0f);
		
		// 设置显示的标题
		this.setTitle(i18n(R.string.video_call_title, toFriend.getNickNameWithRemark()));
		
		//-------------------------------------------------------------------------------
		viewTimer = (TextView)this.findViewById(R.id.video_room_timerView);
		timerViewWrapper = new TimerViewWrapper(this){
			@Override
			protected void timerChanged(String hh_mm_ssStr) {
				viewTimer.setText(hh_mm_ssStr);
			}
		};
		// 开时计时
		timerViewWrapper.start();
		
		//------------------------------------------------------------------------------- 音视频相关
		video_room_videoOrOnlyVoiceSwitchBtn = findViewById(R.id.video_room_videoOrOnlyVoiceSwitchBtn);
		video_room_exitChattingBtn = findViewById(R.id.video_room_exitChattingBtn);
		video_room_hintView = findViewById(R.id.video_room_hintView);
		mainLl = findViewById(R.id.video_room_videosAndSoOnMainLL);
		video_room_voiceOnlyHintRL = findViewById(R.id.video_room_voiceOnlyHintRL);
		video_room_voiceAndVideoRL = findViewById(R.id.video_room_voiceAndVideoRL);
		
		//------------------------------------------------------------------------------- 相关控制组件
		mCameraSwitchImage = findViewById(R.id.image_switch_camera);
		
		// 初始化按钮事件处理
		initListeners();
		
		// 定义全局的 mWakeLock，通过对它的控制来屏幕常亮
		this.powerManager = (PowerManager)this.getSystemService(Context.POWER_SERVICE);
		this.wakeLock = this.powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "RainbowChat:My Lock VideoActivityNew");
	}

	/**
	 * 初始化各件ui事件处理。
	 */
	private void initListeners() {
		// 停止按钮事件处理
		video_room_exitChattingBtn.setOnClickListener(v -> exitChatting());
		// 音频和视频切换按钮事件处理
		video_room_videoOrOnlyVoiceSwitchBtn.setOnCheckedChangeListener((buttonView, isChecked) -> {
			if(ignorevideoOrOnlyVoiceSwitchBtnEvent) {
				ignorevideoOrOnlyVoiceSwitchBtnEvent = false;
			} else {
				// 音视频模式切换（checked==false时表示要切换到音频+视频模式，首次时就是这个默认值，false时表示切换到仅音频聊天模式）
				if(isChecked) {
					switchToVoiceOnlyAsync();
				} else {
					switchToVoiceAndVideoAsync();
				}
			}
		});
		// 前置后置摄像头切换按钮事件处理
		mCameraSwitchImage.setOnClickListener(v -> switchCamera());
	}
	
	/**
	 * 聊天模式。
	 * 
	 * @return true表示处于音频+视频聊天模式，否则表示仅处于音频聊天模式
	 */
	public boolean isVideoAndVoiceChatting() {
		return !video_room_videoOrOnlyVoiceSwitchBtn.isChecked();
	}

	private void switchToVoiceAndVideoAsync() {
		// 新聊天框架中的网络数据发送需要放到异步线程里（Android2.3以上版本要求网络交互不允许发生在主线程里）
		new NewAsyncTask<Object, Integer, Integer>(){
			@Override
			protected Integer doInBackground(Object... params) {
				return MessageHelper.sendVideoAndVoice$SwitchToVoiceAndVideo_from$a(VideoActivityNew.this, toFriend.getUser_uid());
			}

			@Override
			protected void onPostExecute(Integer code) {
				if (code != 0) {
					WidgetUtils.showToast(VideoActivityNew.this, i18n(R.string.video_call_send_voice_video_instruct_failure, toFriend.getNickNameWithRemark(), toFriend.getUser_uid(), toFriend.getUser_mail()), ToastType.WARN);
				}

				switchToVoiceAndVideo(false);
			}
		}.execute();
	}

	private void switchToVoiceOnlyAsync() {
		// 新聊天框架中的网络数据发送需要放到异步线程里（Android2.3以上版本要求网络交互不允许发生在主线程里）
		new NewAsyncTask<Object, Integer, Integer>(){
			@Override
			protected Integer doInBackground(Object... params) {
				return MessageHelper.sendVideoAndVoice$SwitchToVoiceOnly_from$a(VideoActivityNew.this, toFriend.getUser_uid());
			}

			@Override
			protected void onPostExecute(Integer code) {
				if(code != 0) {
					WidgetUtils.showToast(VideoActivityNew.this, i18n(R.string.video_call_send_voice_instruct_failure, toFriend.getNickNameWithRemark(), toFriend.getUser_uid(), toFriend.getUser_mail()), ToastType.WARN);
				}

				switchToVoiceOnly(false);
			}
		}.execute();
	}

	/**
	 * 切换到音频+视频模式.
	 */
	public void switchToVoiceAndVideo(boolean ignorevideoOrOnlyVoiceSwitchBtnEvent) {
		this.ignorevideoOrOnlyVoiceSwitchBtnEvent = ignorevideoOrOnlyVoiceSwitchBtnEvent;
		
		// 单独恢复本地视频预览组件的显示：由于录和放两个SurfaceView存在，而本地的
		// 预览是设置了top显示的，如果不设置它不可见的话，在它上面开启layout是盖不住的（不是SurfaceView的特性决定的，无法改变）
		localSurfaceView.setVisibility(View.VISIBLE);
		switchModel(true);
		
		showHint(this.getString(R.string.video_call_common_hint), false);

		mainLl.setBackgroundColor(this.getResources().getColor(R.color.voip_video_chatting_main_bg));
		video_room_voiceOnlyHintRL.setVisibility(View.GONE);
		video_room_voiceAndVideoRL.setVisibility(View.VISIBLE);
		
		if(ignorevideoOrOnlyVoiceSwitchBtnEvent)
			video_room_videoOrOnlyVoiceSwitchBtn.setChecked(false);
	}
	
	/**
	 * 切换到纯音频模式.
	 */
	public void switchToVoiceOnly(boolean ignorevideoOrOnlyVoiceSwitchBtnEvent) {
		this.ignorevideoOrOnlyVoiceSwitchBtnEvent = ignorevideoOrOnlyVoiceSwitchBtnEvent;
		
		// 单独设置本地视频预览组件不显示：由于录和放两个SurfaceView存在，而本地的
		// 预览是设置了top显示的，如果不设置它不可见的话，在它上面开启layout是盖不住的（不是SurfaceView的特性决定的，无法改变）
		localSurfaceView.setVisibility(View.GONE);
		switchModel(false);
		
		showHint(ignorevideoOrOnlyVoiceSwitchBtnEvent ? getString(R.string.video_call_voice_video_close) : getString(R.string.video_call_voice_running), false);

		mainLl.setBackgroundColor(this.getResources().getColor(R.color.voip_video_chatting_onlyvoice_bg));
		video_room_voiceOnlyHintRL.setVisibility(View.VISIBLE);
		video_room_voiceAndVideoRL.setVisibility(View.GONE);
		
		if(ignorevideoOrOnlyVoiceSwitchBtnEvent)
			video_room_videoOrOnlyVoiceSwitchBtn.setChecked(true);
	}
	
	private void switchModel(boolean videoAndVoice) {
		if(videoAndVoice) {
			myController.switchVideoChat(toAccount);
			chatType = VcConstants.VIDEO;
		}
		// only voice
		else {
			myController.switchAudioChat(toAccount);
			chatType = VcConstants.AUDIO;
		}
	}
	
	/**
	 * 显示提示信息.
	 * 
	 * @param hintText
	 */
	public void showHint(String hintText, boolean playAudioPrompt) {
		showHint(hintText, false, playAudioPrompt);
	}
	/**
	 * 显示提示信息.
	 * 
	 * @param hintText
	 */
	public void showHint(String hintText, boolean andShowToast, boolean playAudioPrompt) {
		this.video_room_hintView.setText(hintText);
		if(andShowToast)
			WidgetUtils.showToast(this, hintText, ToastType.INFO);
		if(playAudioPrompt)
			// 播放提示音
			PromtHelper.playendPromt(VideoActivityNew.this);
	}
	
	/**
	 * 退出音视频聊天.
	 */
	public void exitChatting() {
		new AlertDialog.Builder(VideoActivityNew.this)
			.setTitle(VideoActivityNew.this.getResources().getString(R.string.general_prompt))
			.setMessage(VideoActivityNew.this.getResources().getString(R.string.video_call_exit_talking_confirm))
			.setPositiveButton(VideoActivityNew.this.getResources().getString(R.string.general_ok), (dialog, which) -> exitChattingNoConfirm())
			.setNegativeButton(VideoActivityNew.this.getResources().getString(R.string.general_cancel), null)
			.show();
	}

	public void exitChattingNoConfirm() {
		try {
			int code = MessageHelper.sendVideoAndVoice$EndChatting_from$a(VideoActivityNew.this
					, toFriend.getUser_uid(), MyApplication.getInstance2().getIMClientManager().getLocalUserInfo().getUser_uid());
			if(code == 0) {
				// 发出一条音视频聊天记录（这样的话，本地和远端都会有记录的哟）
				MessageHelper.sendVoipRecordMessageAsync(
						// context用全局Application对象，确保消息的发送不依赖于本Activity的生命周期
						MyApplication.getInstance2()
						, toFriend.getUser_uid()
						, new VoipRecordMeta(VoipRecordMeta.VOIP_TYPE_VIDEO, VoipRecordMeta.RECORD_TYPE_CHATTING_DURATION, timerViewWrapper.getTotoalSecond())
						, null);

				WidgetUtils.showToast(VideoActivityNew.this, i18n(R.string.video_call_send_exit_instruct, toFriend.getNickNameWithRemark()), ToastType.OK);
				// 播放提示音
				PromtHelper.playendPromt(VideoActivityNew.this);
			} else {
				WidgetUtils.showToast(VideoActivityNew.this, i18n(R.string.video_call_send_exit_instruct_failure, toFriend.getNickNameWithRemark(), toFriend.getUser_uid(), toFriend.getUser_mail()), ToastType.WARN);
			}
			
			finish();
		} catch (Exception e) {
			WidgetUtils.showToast(VideoActivityNew.this, e.getMessage(), ToastType.WARN);
		}
	}
	
	/**
	 * 捕获back键.
	 */
	@Override
	public void onBackPressed() {
		exitChatting();
	}

	protected void onResume() {
		isBack = false;
		startOrientationListener();

		super.onResume();
		
		// 设置BaseEvent观察者
		MyApplication.getInstance2().getIMClientManager().setCurrentVideoChattingActivity(this);
		
		//-----------------------------------------------------------------------------------
		// 开始屏幕长亮
		this.wakeLock.acquire();
	}

	protected void onPause() {
		isBack = true;
		super.onPause();
		
		// 设置BaseEvent观察者
		MyApplication.getInstance2().getIMClientManager().setCurrentVideoChattingActivity(null);
		
		// 取消屏幕长亮
		this.wakeLock.release();
	}

	@Override
    protected void onStop() {
    	super.onStop();
    }
	
	protected void onDestroy() {
		Log.d(TAG, "VideoChatActivity.onDestroy begin");
		
        //如果非正常退出/正常退出，都会触发onDestroy在此处结束
        if(p2pController!=null) {
            p2pController.unRegistryRequestEventListener(this);
        	if(chatType==VcConstants.VIDEO)
                p2pController.closeAction(AccountManager.myAccount,toAccount,VcConstants.VIDEO);
        	else if(chatType==VcConstants.AUDIO)
        		p2pController.closeAction(AccountManager.myAccount,toAccount,VcConstants.AUDIO);
        }

        //一定要调父类的销毁方法
		release();

		chatting = false;
		timerViewWrapper.stop();

        super.onDestroy();

		Log.d(TAG, "VideoChatActivity.onDestroy end");
		// 结束Activity&从堆栈中移除
		AppManager.getAppManager().removeActivity(this);
	}
	
	//------------------------------------------------------------------------------------------------------
	private final Handler handler = new Handler() {
		@Override
		public void handleMessage(Message msg) 
		{
        	Log.d(TAG, "handler.handleMessage|current thread="+Thread.currentThread());
        	
			Bundle data = msg.getData();
			long fromAccount = data.getLong("fromAccount",0);
			switch(msg.what) {
				case VcConstants.TYPE_REJECT_VIDEO_BY_FRIEND: {
					Log.d(TAG, fromAccount+"拒绝了视频请求！");
					finish();
					break;
				}
				case VcConstants.TYPE_REJECT_AUDIO_BY_FRIEND: {
					Log.d(TAG, fromAccount+"拒绝了语音请求！");
					finish();
					break;
				}
				case VcConstants.TYPE_CLOSED_VIDEO_BY_FRIEND: {
					Log.d(TAG, fromAccount+"关闭了视频通话！");
					break;
				}
				case VcConstants.TYPE_CLOSED_AUDIO_BY_FRIEND: {
					Log.d(TAG, fromAccount+"关闭了语音通话！");
					break;
				}
				case VcConstants.TYPE_PAUSE_VIDEO_BY_FRIEND: {
					Log.d(TAG, fromAccount+"暂停了视频！");
					break;
				}
				case VcConstants.TYPE_RESUME_VIDEO_BY_FRIEND: {
					Log.d(TAG, fromAccount+"已继续视频！");
					break;
				}
				case VcConstants.TYPE_SWITCH_AUDIO_FRIEND: {
					Log.d(TAG, fromAccount+"已切换到语音通话！");
					break;
				}
				case VcConstants.TYPE_SWITCH_VIDIO_FRIEND: {
					Log.d(TAG, fromAccount+"已切换到视频通话！");
					break;
				}
				// 接受了请求，视频+语音通话中...
				case VcConstants.TYPE_ACCEPT_VIDEO_BY_FRIEND: {
					if(myController != null) {
						audioStart();
						// 打开麦克风，开始传数据出去
						myController.mMicphone = false;
						// 先不开启声音，待对方接收后再放开
						myController.mSound = false;
						break;
					}
					else {
						Log.e(TAG, "》myController为Null？？");
						return;
					}
				}
				// 接受了请求，语音通话中...
				case VcConstants.TYPE_ACCEPT_AUDIO_BY_FRIEND: {
					audioStart();
					//打开麦克风，开始传数据出去
					myController.mMicphone = false;
					//开启声音，接收对方传过来的声音数据播放
					myController.mSound = false;
					break;
				}
				case VcConstants.TYPE_CONNECT_P2P_FAILED: {
					Log.d(TAG, "【VV】与对方连接建立失败，通话结束...");
					break;
				}
			}
		}
	};

	/**
	 * 音视频SDK层反馈过来的事件。
	 *
	 * @param eventId 事件id
	 * @param fromAccount 来自uid
	 * @param detail
	 */
	@Override
	public void onReceiveEvent(int eventId, long fromAccount, byte[] detail) {
		if(!isBack) {
			Message msg = new Message();
			msg.what = eventId;
			Bundle bundle = new Bundle();
			bundle.putLong("fromAccount",fromAccount);
			bundle.putByteArray("detail",detail);
			msg.setData(bundle);
			handler.sendMessage(msg);
		}
	}

	/**
	 * 摄像头切换。
	 */
	public void switchCamera() {
		Runnable r = new SwitchCameraRunnable(R.id.surface_local);
		r.run();
	}

	public static boolean isChatting() {
		return chatting;
	}

	private String i18n(int messageFormatPatternResId, Object... arguments){
		return ToolKits.i18n(this, messageFormatPatternResId, arguments);
	}
}